package sw6.admin;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.xml.sax.SAXException;

import sw6.admin.gui.AppEntry;
import sw6.admin.gui.logic.Menu;
import sw6.admin.gui.logic.Serializer;
import sw6.admin.gui.logic.SettingParser;
import sw6.admin.parser.SettingsParser;
import sw6.lib.internal.PrivateDefinitions;
import android.app.ListActivity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

/**
 * This class is the program entry. It displayes a list of all installed giraf apps and a general settings shortcut.
 * 
 * 	- When the user clicks on an app in the list, an activity (MenuActivity) displaying the settings for the app wil be lauched.
 * 	- When the user clicks on the generals settings shortcut an activity (MenuActivity) displaying the genneral settings for the device will be launched
 *  - 
 *  
 * @author sw6b
 *
 */
public class MainActivity extends ListActivity {

	ArrayList<AppEntry> mAppEntries;
	AppAdapter mAdapter;

	/**
	 * When the admin program is launched, onCreate is the first method to be called.
	 */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		Bundle extra = getIntent().getExtras();
		if (extra != null)
		{
			if (extra.containsKey("packageName") == true) {
				String packageName = extra.getString("packageName");
				loadSettingsForApp(packageName);
				finish();
			}
		}
	}
	
	@Override
	public void onResume() {
		super.onResume();
		loadApps();
	}

	/**
	 * Loads all app installed, and filters away all non-giraf apps. The Giraf apps are then
	 * used to populate the ListActivity. In other words, a list of all giraf apps are shown
	 * in the GUI
	 */
	private void loadApps() {
		
		mAppEntries = new ArrayList<AppEntry>();
		mAdapter = new AppAdapter(this, R.layout.app_entry, mAppEntries);
		setListAdapter(mAdapter);
		
		// Loads the names of the apps. Only apps that have the graf prefix on theyr packageName and who have a settings file will be loaded
		final PackageManager pm = getPackageManager();
		List<ApplicationInfo> installedApplications = pm.getInstalledApplications(0);

		Collections.sort(installedApplications, new Comparator<ApplicationInfo>() {
			@Override
			public int compare(ApplicationInfo arg0, ApplicationInfo arg1) {
				String arg0Label = arg0.loadLabel(pm).toString();
				String arg1Label = arg1.loadLabel(pm).toString();

				return arg0Label.compareTo(arg1Label);
			} });

		mAdapter.add(new AppEntry(getString(R.string.administrative_settings), this.getResources().getDrawable(R.drawable.icon_giraf_admin), PrivateDefinitions.SW6_ADMIN_PACKAGE_NAME));
		mAdapter.add(new AppEntry(getString(R.string.giraf_place_start), this.getResources().getDrawable(R.drawable.icon), PrivateDefinitions.SW6_ADMIN_PACKAGE_NAME));

		for (ApplicationInfo app : installedApplications) {
			if (app.packageName.startsWith(PrivateDefinitions.GIRAF_APP_PREFIX) == false || app.packageName.equals(PrivateDefinitions.SW6_ADMIN_PACKAGE_NAME))
				continue;
			if (hasVisibleSettings(app.packageName) == false)
				continue;

			mAdapter.add(new AppEntry(app.loadLabel(pm).toString(), pm.getApplicationIcon(app), app.packageName));
		}
	}

	private boolean hasVisibleSettings(String packageName) {
		try {
			// Retrieves the asset manager for the app in question
			AssetManager am = SettingsParser.getAssetsByAppName(MainActivity.this, packageName);
			
			InputStream is = am.open(PrivateDefinitions.SETTINGS_FILE_NAME);

			// Parses the settings file for the app as a tree structure with root "menu"
			Menu menu = SettingParser.loadXML(is, packageName, this.getPackageManager());
			
			// Check if there are any visible settings in the packages settings.xml file
			if (menu.getSettings().size() == 0 && menu.getMenus().size() == 0) {
				return false;
			}
			else {
				return true;
			}
		} catch (NameNotFoundException e) {
			e.printStackTrace();
			return false;
		} catch (IOException e) {
			// This is a valid Exception catch because we get this if the package not have any settings.xml file
			return false;
		} catch (SAXException e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * Starts a new activity, displaying the settings for a given app
	 * @param packageName The package name of the app, whos settings is to be displayed
	 */
	private void loadSettingsForApp(String packageName){
		try {
			// Retrieves the asset manager for the app in question
			AssetManager am = SettingsParser.getAssetsByAppName(MainActivity.this, packageName);
			InputStream is = am.open(PrivateDefinitions.SETTINGS_FILE_NAME);

			// Parses the settings file for the app as a tree structure with root "menu"
			Menu menu = SettingParser.loadXML(is, packageName, this.getPackageManager());

			// Serialized menu so that it can be sent to MenuActivity
			byte[] bytes = Serializer.serializeObject(menu);
			Intent intent = new Intent();

			intent.setClassName(this, "sw6.admin.gui.MenuActivity");
			intent.putExtra("menuBytes", bytes);

			startActivity(intent);

		} catch (IOException e) {
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Calls loadSettingsForApp when a user clicks on an app
	 */
	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		
		// Check if the user selected GIRAF Place
		if(mAppEntries.get(position).getRealName().equals(getString(R.string.giraf_place_start))) {
			Intent intent = new Intent(this, sw6.girafplaceclient.MainActivity.class);
			startActivity(intent);
		} else {
			// Loads settings for the app that the user clicked on
			loadSettingsForApp(mAppEntries.get(position).getPackageName());
		}
		super.onListItemClick(l, v, position, id);
	}

	private class AppAdapter extends ArrayAdapter<AppEntry> {

		private ArrayList<AppEntry> items;

		public AppAdapter(Context context, int textViewResourceId, ArrayList<AppEntry> items) {
			super(context, textViewResourceId, items);
			this.items = items;
		}
		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			View view = convertView;
			LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
			view = vi.inflate(R.layout.app_entry, null);

			AppEntry appEntry = items.get(position);
			TextView textView = (TextView) view.findViewById(R.id.toptext);
			ImageView imageView = (ImageView) view.findViewById(R.id.icon);
			imageView.setImageDrawable(appEntry.getIcon());
			textView.setText(appEntry.getRealName());

			return view;
		}
	}
}